package global;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import bufmgr.*;
import diskmgr.PCounter;
import heap.*;
import iterator.*;

public class CommandLine {

	public static String dbPath = "cse_510.minibase-db";
	// TODO: How many pages do we want to use???
	public static int dbPages = 8000;
	public static int SORTPGNUM = 50;
	//public static Schema schema1;

	public static void main(String[] args) throws HFException, HFBufMgrException, HFDiskMgrException, InvalidTypeException, InvalidTupleSizeException, FileScanException, TupleUtilsException, InvalidRelation, JoinsException, PageNotReadException, PredEvalException, UnknowAttrType, FieldNumberOutOfBoundException, WrongPermat, IOException, PageUnpinnedException, PagePinnedException, PageNotFoundException, BufMgrException, HashOperationException, HashEntryNotFoundException, InvalidFrameNumberException, ReplacerException {
		// MY: moved code that was here to queryCommand()
		if (args.length > 0)	// arguments passed, try to run command directly
		{
			if (executeCommand(args)) return;

		}
		// run command prompt to initialize and accept commands
		commandPrompt();
	}

    // Determines the command based on the arguments given and runs it

	private static boolean executeCommand(String[] args)
	{
		boolean handled = true;

		if ( args[0].equals("oldinsert") )
		{
			Commands.batchCommand(args);
		}
		else if (args[0].equals("batchinsert"))
		{
			Commands.batchInsert(args);
		}
		else if (args[0].equals("batchcreate"))
		{
			Commands.batchCreate(args);
		}
        else if (args[0].equals("batchdelete"))
        {
            Commands.batchDelete(args);
        }
		else if (args[0].equals("vaindex"))
		{
			Commands.vaIndex(args);
		}
		else if (args[0].equals("query"))
		{
			QueryCommand.query(args);
		}
		else
		{
			handled = false;
		}
		
		if (handled)
		{
			finalizeCommand();
		}
		
		return handled;
	}

    // Provides a command prompt to enter in queries

	private static void commandPrompt() {
		
		BufferedReader in = new BufferedReader (new InputStreamReader(System.in));
		System.out.println("Enter commands at the prompt.");
		System.out.println("Enter 'quit' or 'exit' to quit application.");
		String cmd;
		while (true)
		{
			System.out.print("Command:> ");
			try 
			{
				cmd = in.readLine();
				if (cmd.toLowerCase().equals("exit") || cmd.toLowerCase().equals("quit"))
				{
					break;
				}
				String[] args = cmd.split(" ");
				if (args[0].equals("suppress"))
				{
					Commands.verbose = false;
					System.out.println("Minimal output, will not output tuples.");
				}
				else if (args[0].equals("verbose"))
				{
					Commands.verbose = true;
					System.out.println("Verbose output, will output tuples.");
				}
				else if (!executeCommand(args))
				{
					System.out.println("Unrecognized Command");
				}
			} 
			catch (IOException e) {
				System.err.println("Error reading command: " + e.getMessage());
			}
		}
	}

    // Sets up the database for use in a command

	public static void initializeDB()
	{
		initializeDB(dbPath, true, GlobalConst.NUMBUF);
	}
	public static void initializeDB(boolean useExistingDB)
	{
		initializeDB(dbPath, useExistingDB, GlobalConst.NUMBUF);
	}
	public static void initializeDB(int numBuffers)
	{
		initializeDB(dbPath, true, numBuffers);
	}
	public static void initializeDB(String path, boolean useExistingDB, int numBuffers)
	{
		SystemDefs.MINIBASE_RESTART_FLAG = useExistingDB;
		SystemDefs sysdef = new SystemDefs(path, CommandLine.dbPages, numBuffers ,"Clock");
		// initialize counter so we can count pages written and read
		PCounter.initialize();
	}

    // Performs cleanup on the database at the completion of a command

	public static void finalizeCommand()
	{
		// flush all the pages
	    try {
			SystemDefs.JavabaseBM.flushAllPages();
		} catch (Exception e) {
			System.err.println("Error flushing pages: " + e.getMessage());
	    }
	    // closing DB. it will be re-opened with each command
	    try {
	    	SystemDefs.JavabaseDB.closeDB();
	    }
	    catch (Exception e) {
			System.err.println("Error closing the database: " + e.getMessage());
	    }

	    // output page count statistics
	    int read = PCounter.counter;
    	int written = PCounter.counterw;
	    System.out.format("Number of data pages written: %d.\n", written);
	    System.out.format("Number of data pages read: %d.\n", read);
		
	}

	// Mark Yates - a projection list FldSpec with all attributes for intermediate iterators
	public static FldSpec[] getFldSpecForAll(AttrType[] attrType)
	{
		RelSpec rel = new RelSpec(RelSpec.outer);
		FldSpec[] allFlds = new FldSpec[attrType.length];
		
		for (int i = 0; i < attrType.length; i++) {
			allFlds[i] = new FldSpec(rel, i+1);
		}
		return allFlds;
	}
	
}
